/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __Thread_H__
#define __Thread_H__

#pragma once

namespace thread {

/**
 * A Runnable interface.<br>
 * A class that wishes to be used as thread should implement this.<br>
 * It should then create a thread with this class as interface.
 */
struct DLL_EXPORT IRunnable 
{
	/// The run method should be implemented. run() is called during starting of the Thread class
	virtual void run() = 0;
};


/**
 * \ingroup CoreEngine
 *
 * The Thread class.<br>
 * At the moment starting and stopping of the thread are supported.<br>
 * To use this, create a private member of Thread and inherit from IRunnable.<br>
 * Implement the run method and create the Thread object with that class as argument.
 *
 * \date 03-28-2007
 *
 * \author juckel
 *
 */
class DLL_EXPORT Thread
{
public:
	/// Creates a new thread from the specified pointer
	Thread( IRunnable*	ptr );
	virtual ~Thread(void);

	/// Starts the thread
	virtual void start();

	/// Stops the thread
	virtual void stop();

	/// Resumes a suspended thread
	void resume();

	/// Lets the thread sleep for a couple of milliseconds
	void sleep(long milliseconds);

	/// Kills the thread execution
	void kill();

	const HANDLE& getHandle() const;

private:
	/// The multi-threaded object
	IRunnable *pRunnableObj;

	/// The window handle to the thread
	HANDLE hThread;
};


/**
 * \ingroup CoreEngine
 *
 * The Mutex class.<br>
 * Create a Mutex to use the synchronized method like such: 
 * In header: static thread::Mutex mutex;
 * In cpp:    
 * synchronized(mutex) {
 *   .. some code ..
 * }
 *
 * \date 09-12-2007
 *
 * \author juckel
 *
 */
class DLL_EXPORT Mutex
{
public:
    /// The default constructor
    Mutex();
    /// Destructor
    virtual ~Mutex();
    /// lock
    void lock();
    /// unlock
    void unlock();

private:
    CRITICAL_SECTION m_criticalSection;
};


/**
 * \ingroup CoreEngine
 *
 * The Lock class.<br>
 * A synchronization controller object. 
 * <b>Don't use directly</b>
 *
 * \date 09-12-2007
 *
 * \author juckel
 *
 */
class DLL_EXPORT Lock
{
public:
    /// The default constructor
    Lock(Mutex &mutex);

    /// The destructor
    ~Lock();

    /// Report the state of locking when used as a boolean
    operator bool () const {
        return m_locked;
    }

    /// Unlock
    void setUnlock() {
        m_locked = false;        
    }

private:
    Mutex &m_mutex;
    bool m_locked;
};

#ifndef _SYNCHRONIZED
#define _SYNCHRONIZED
#define synchronized(M)  for(thread::Lock M##_lock = M; M##_lock; M##_lock.setUnlock())
#endif

} // namespace

#endif
